package com.wfh.rpc.registry;

import cn.hutool.json.JSONUtil;
import com.wfh.rpc.model.RegistryConfig;
import com.wfh.rpc.model.ServiceModelInfo;
import io.etcd.jetcd.*;
import io.etcd.jetcd.api.Kv;
import io.etcd.jetcd.options.GetOption;
import io.etcd.jetcd.options.PutOption;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Title: EtcdRegistry
 * @Author wangfenghuan
 * @Package com.wfh.rpc.registry
 * @Date 2025/10/14 14:09
 * @description: etcd注册中心
 */
public class EtcdRegistry implements Registry {

    private Client client;

    private KV kvClient;

    /**
     * 根节点
     */
    private static final String ETCD_ROOT_PATH = "/rpc/";

    @Override
    public void init(RegistryConfig registryConfig) {
        client = Client.builder().endpoints(registryConfig.getAddress()).connectTimeout(Duration.ofMillis(registryConfig.getTimeout())).build();
        kvClient = client.getKVClient();
    }

    /**
     * 服务注册
     * @param serviceModelInfo
     * @throws Exception
     */
    @Override
    public void register(ServiceModelInfo serviceModelInfo) throws Exception {
        Lease leaseClient = client.getLeaseClient();
        // 创建一个30妙的租约
        long leadeId = leaseClient.grant(30).get().getID();
        // 设置要存储的键值对
        String registerKey = ETCD_ROOT_PATH + serviceModelInfo.getServiceNodeKey();
        ByteSequence key = ByteSequence.from(registerKey, StandardCharsets.UTF_8);
        ByteSequence value = ByteSequence.from(JSONUtil.toJsonStr(serviceModelInfo), StandardCharsets.UTF_8);

        // 将键值对和租约关联卡里，并设置过期时间
        PutOption putOption = PutOption.newBuilder().withLeaseId(leadeId).build();
        kvClient.put(key, value, putOption).get();
    }

    /**
     * 服务注销
     * @param serviceModelInfo
     */
    @Override
    public void unRegister(ServiceModelInfo serviceModelInfo) {
        kvClient.delete(ByteSequence.from(ETCD_ROOT_PATH + serviceModelInfo.getServiceNodeKey(), StandardCharsets.UTF_8));
    }

    /**
     * 服务发现
     * @param serviceKey
     * @return
     */
    @Override
    public List<ServiceModelInfo> serviceDiscovery(String serviceKey) {
        String searchPrefix = ETCD_ROOT_PATH + serviceKey + "/";
        try{
            GetOption getOption = GetOption.newBuilder()
                    .isPrefix(true).build();
            List<KeyValue> kvs = kvClient.get(ByteSequence.from(searchPrefix, StandardCharsets.UTF_8), getOption)
                    .get()
                    .getKvs();
            // 解析服务信息
            return kvs.stream().map(kv -> {
                String value = kv.getValue().toString(StandardCharsets.UTF_8);
                return JSONUtil.toBean(value, ServiceModelInfo.class);
            }).collect(Collectors.toList());
        }catch (Exception e){
            throw new RuntimeException("获取服务列表失败", e);
        }
    }

    /**
     * 服务销毁
     */
    @Override
    public void destory() {
        System.out.println("当前节点下线");
        // 释放资源
        if (kvClient != null) {
            kvClient.close();
        }
        if (client != null) {
            client.close();
        }
    }

}
